class Singleton {
    static instance: any;
    constructor() {
        if (typeof Singleton.instance === 'object') {
            return Singleton.instance;
        }
        Singleton.instance = this;
    }

    static getInstance() {
        if (!Singleton.instance) {
            Singleton.instance = new this();
        }
        return Singleton.instance;
    }
}

export default class EventManager extends Singleton {
    subscribes: {};
    m_emit_reference_count: number;
    constructor() {
        super();
        this.subscribes = {};
        this.m_emit_reference_count = 0;
    }

    public on(name, func, target?) {
        if (!this.subscribes[name]) {
            this.subscribes[name] = [];
        }
        const subscription = { f: func, del: false, target: target };
        this.subscribes[name].push(subscription);

        return () => {
            this.off(name, func);
        };
    }

    public once(name, func, target?) {
        const unsubscribe = this.on(
            name,
            (...args: any[]) => {
                func.apply(target, args);
                unsubscribe();
            },
            target
        );
        return unsubscribe;
    }

    public emit(name, ...args) {
        ++this.m_emit_reference_count;
        const subscriptions = this.subscribes[name];
        if (subscriptions) {
            subscriptions.forEach((subscription) => {
                if (subscription.f && !subscription.del) {
                    subscription.f.apply(subscription.target, args);
                }
            });
        }
        --this.m_emit_reference_count;
        if (this.m_emit_reference_count === 0) {
            this.clear();
        }
    }

    public off(name, func) {
        const subscriptions = this.subscribes[name];
        if (subscriptions) {
            if (func) {
                subscriptions.forEach((subscription) => {
                    if (subscription.f === func) {
                        subscription.del = true;
                    }
                });
            } else {
                subscriptions.forEach((subscription) => {
                    subscription.del = true;
                });
            }
        }
        if (this.m_emit_reference_count === 0) {
            this.clear();
        }
    }

    private clear() {
        for (const name in this.subscribes) {
            this.subscribes[name] = this.subscribes[name].filter((v) => !v.del);
        }
    }
}

/**
 * 事件管理器
 */
// class Singleton{

// }
// export default class EventManager extends Singleton{
//     //监听
//     public on(name, func, target?) {
//         if (!this.subscribes[name]) {
//             this.subscribes[name] = [];
//         }
//         this.subscribes[name].push({ f: func, del: false, target: target });
//         return () => {
//             this.off(name, func);
//         };
//     }

//     //监听运行一次
//     public once(name, func, target?) {
//         let unsubscribe = undefined;
//         unsubscribe = this.on(
//             name,
//             (...args: any[]) => {
//                 func.apply(target, args);
//                 unsubscribe();
//             },
//             target
//         );
//         return unsubscribe;
//     }

//     //派发所有监听
//     public emit(name, ...args) {
//         ++this.m_emit_reference_count;
//         if (this.subscribes[name]) {
//             this.subscribes[name].forEach((v) => {
//                 if (v.f && !v.del) {
//                     v.f.apply(v.target, args);
//                 }
//             });
//         }
//         --this.m_emit_reference_count;
//         return;
//     }

//     //取消监听
//     public off(name, func) {
//         if (this.subscribes[name]) {
//             if (func) {
//                 this.subscribes[name].forEach((v) => {
//                     if (v.f === func) {
//                         v.del = true;
//                     }
//                 });
//             } else {
//                 this.subscribes[name].forEach((v) => {
//                     v.del = true;
//                 });
//             }
//         }
//         if (this.m_emit_reference_count === 0) {
//             this.clear();
//         }
//     }

//     //清除监听
//     private clear(){

//         for(let name in this.subscribes){
//             this.subscribes[name] = this.subscribes[name].filter((v)=>!v.del)
//         }
//     }
// }


// // 调用形式如下
// EventManager.getInstance().on('enent_init',test(),test1) 请补充Singleton并且检查完善该事件管理器代码